/////////////////////////////////////////////////////////////////////////////////////
// vertex programs

struct vert_in
{
	float4 f4Position  : ATTR0;
	float2 f2TexCoord0 : ATTR1;
	float2 f2TexCoord1 : ATTR2;
};

struct vert_out
{
	float4 f4Position  : POSITION;
	float2 f2TexCoord0 : TEXCOORD0;
	float2 f2TexCoord1 : TEXCOORD1;
	float1 f1FogExp    : TEXCOORD2;
};

vert_out vertex( 
	vert_in vi, 
	uniform float4x4 f44ModelView, 
	uniform float4x4 f44ModelViewProj )
{
	// fog
	//float1 f1FogDensity = -log2(500);
	float1 f1FogDensity = 1.0 / 500.0;
	float3 f3EyePos     = mul(vi.f4Position, f44ModelView).xyz;
	float1 f1FogDist    = length(f3EyePos);

	// output
	vert_out vo;
	vo.f4Position  = mul(vi.f4Position, f44ModelViewProj);
	vo.f2TexCoord0 = vi.f2TexCoord0;
	vo.f2TexCoord1 = vi.f2TexCoord1;
	vo.f1FogExp    = f1FogDist * f1FogDensity;
	return vo;
}

/////////////////////////////////////////////////////////////////////////////////////
// fragment programs

struct frag_in
{
	float2 f2TexCoord0 : TEXCOORD0;
	float2 f2TexCoord1 : TEXCOORD1;
	float1 f1FogExp    : TEXCOORD2;
};

struct frag_out
{
	float4 f4Color : COLOR;
};

frag_out fragment( 
	frag_in fi, 
	uniform sampler2D sampWater0, 
	uniform sampler2D sampWater1 )
{
	// fragment color
	float4 f4FragColor = 
		float4( tex2D(sampWater0, fi.f2TexCoord0).rgb, 0.75 ) * 0.5 + // water 1
		float4( tex2D(sampWater1, fi.f2TexCoord1).rgb, 0.75 ) * 0.5;  // water 2

	// fog color
	float4 f4FogColor = float4(0.63, 0.76, 0.94, 1.00);

	// fog density
	//float1 f1Fog = exp2(-abs(fi.f1FogExp));
	float1 f1Fog = 1.0 - min(sqrt(fi.f1FogExp), 1.0);

	// output
	frag_out fo;
	fo.f4Color = lerp(f4FogColor, f4FragColor, (float)f1Fog);
	return fo;
}

/////////////////////////////////////////////////////////////////////////////////////
// techniques

float4x4 g_matModelView;
float4x4 g_matModelViewProj;

sampler2D Water1Sampler;
sampler2D Water2Sampler;

technique water_tech_nvidia
{
	pass water_tech_nvidia_pass0
	{
		DepthTestEnable  = true;
		AlphaBlendEnable = true;
		BlendFunc        = int2(SrcAlpha, InvSrcAlpha);

		VertexProgram   = compile gp5vp vertex(g_matModelView, g_matModelViewProj);
		FragmentProgram = compile gp5fp fragment(Water1Sampler, Water2Sampler);
	}
}

technique water_tech_amd
{
	pass water_tech_amd_pass0
	{
		DepthTestEnable  = true;
		AlphaBlendEnable = true;
		BlendFunc        = int2(SrcAlpha, InvSrcAlpha);

		VertexProgram   = compile arbvp1 vertex(g_matModelView, g_matModelViewProj);
		FragmentProgram = compile arbfp1 fragment(Water1Sampler, Water2Sampler);
	}
}
